package classes{
	import classes.utils.Utility;
	import classes.utils.Validator;
	
	import mx.collections.ArrayCollection;
	import mx.collections.Sort;
	import mx.collections.SortField;
	

	[Bindable]
	public class Account implements WritableObject
	{
		public var compContribution:Number = 0;
		public var userContribution:Number = 0;
		public var accountType:String;
		public var accountName:String = "";
		public var type:String = "";
		public var transactions:ArrayCollection = new ArrayCollection();
		public var statementStart:String = "1";
		//public var statementEnd:Number = 0;
		public var minimumBalance:Number;
		public var maximumBalance:Number;
		public var interestRate:Number;
		public var interestCalculationDate:Number;
		public var maximumTransactionsPerStatement:int;
		public var scheduledTransactions:ArrayCollection = new ArrayCollection();
		public var approvalList:ArrayCollection = new ArrayCollection();
		
		public var balance:Number = 0;
		
		public function Account()
		{
			accountType = "normal";
		}
		
		public function parseAccountString(raw:XML):void{
			this.accountName = raw.@accountName;
			this.statementStart = raw.@statementStart;
			this.accountType = raw.@accountType;
			var rawTransactions:XMLList = raw.children();
			
			this.userContribution = raw.@userContribution;
			this.compContribution = raw.@compContribution;
			this.transactions = new ArrayCollection();
			this.scheduledTransactions = new ArrayCollection();
			for(var i:int = 0; i < rawTransactions.length(); i++){
				var rawT:XML = rawTransactions[i];
				var newT:Transaction = new Transaction();
				newT.parseTransactionString(rawT);
				var scheduled:Boolean = (newT.date.time > new Date().time);
				
				if(newT.isScheduled && !scheduled){
					this.approvalList.addItem(newT);
				}
				
				//check date & isScheduled flags
				else if(newT.isScheduled)
				{
					this.scheduledTransactions.addItem(newT);
				}
				else
				{
					this.transactions.addItem(newT);
				}
			}
			
			var sortField:SortField = new SortField();
			sortField.name = "date";
			var sort:Sort = new Sort();
			sort.fields = [sortField];
			
			//TODO: save default sort option?
			//sort transactions by date, for default
			this.transactions.sort = sort;
			this.transactions.refresh();
			
			this.scheduledTransactions.sort = sort;
			this.scheduledTransactions.refresh();
			
		}
		public function toWritableString():String
		{
			var s:String = "<Account accountName=\"" + this.accountName +
							"\" accountType=\"" + this.accountType + 
							"\" type=\"" + this.type +
							"\" userContribution=\"" + this.userContribution +
							"\" compContribution=\"" + this.compContribution +
							"\" statementStart=\"" + this.statementStart+ 
							"\" minimumBalance=\"" + this.minimumBalance+ 
							"\" maximumBalance=\"" + this.maximumBalance+ 
							"\" interestRate=\"" + this.interestRate +
							"\" interestCalculationDate=\"" + this.interestCalculationDate +
							"\" maximumTransactionPerStatement=\"" + this.maximumTransactionsPerStatement + 
							"\" balance=\"" + this.balance +  "\" >";
			
			
			//for loop iterating through accounts
			var i:int = 0;
			for(i = 0; i < this.transactions.length; i++){
				var transaction:Transaction = this.transactions.getItemAt(i) as Transaction;
				s += transaction.toWritableString();
			}
			for(i = 0; i < this.scheduledTransactions.length; i++){
				var  scheduledTransaction:Transaction = this.scheduledTransactions.getItemAt(i) as Transaction;
				s += scheduledTransaction.toWritableString();
			}
			
			s += "</Account>";
			
			return s;
			//return 
		}
		
		public function calculateBalance():Number{
			this.balance = 0;
			for(var i:int = 0; i < this.transactions.length; i++){
				this.balance += this.transactions.getItemAt(i).amount;
			}
			return this.balance;
		}
		
		public function addTransaction(newTransaction:Transaction):void{
			if(!Validator.validateTransaction(newTransaction)){
				//TODO: display a message?
				return;
			}
			
			if(newTransaction.isScheduled)
				this.scheduledTransactions.addItem(newTransaction);
			else
				this.transactions.addItem(newTransaction);
			
			if(TreasuryModel.getInstance().addTransaction != null)
				TreasuryModel.getInstance().addTransaction.refresh();
				
			TreasuryModel.getInstance().recalculateUserData();
		}
		
		public function deleteTransaction(transaction:Transaction):void{
			var found:Boolean = false;
			var i:int = 0;
			for(; i < this.transactions.length; i++){
				if(this.transactions.getItemAt(i) == transaction){
					this.transactions.removeItemAt(i);
					found = true;
					break;
				}
			}
			
			if(!found){
				for(i = 0; i < this.scheduledTransactions.length; i++){
					if(this.scheduledTransactions.getItemAt(i) == transaction){
						this.scheduledTransactions.removeItemAt(i);
						break;
					}
				}
			}
			
			TreasuryModel.getInstance().recalculateUserData();
		}
		
		/**
		 * statementOffset represents the number of statements before the current date.
		 * 	Zero represents the current statement 
		 */
		public function getTransactionWithinPeriod(statementOffset:Number = 0):Object{
			if(statementOffset < 0)
				statementOffset *= (-1);
			
			var now:Date = new Date();
			
			//todo: externalize for better code..
			var year:Number;
			var month:Number;
			var day:Number;
			
			year = now.fullYear;
			month = now.getMonth() - statementOffset;
			
			//FIXME: something's not quite right with this month-checking
			if(month < 0){
				month = 12 + month;
				year--;
			}
			day = new Number(this.statementStart);
			var rangeStart:Date = new Date(year, month, day, 0, 0, 0, 0);
			
			year = now.fullYear;
			month = now.getMonth() - (statementOffset - 1);
			if(month < 0){
				month = 12 + month;
				year--;
			}
			day = new Number(this.statementStart);			
			var rangeEnd:Date = new Date(year, month, day, 0, 0, 0, 0);
			
			trace(rangeStart.toDateString());
			trace(rangeEnd.toDateString());
			trace("--------------------");

			var filteredTransactions:ArrayCollection = new ArrayCollection();
			var tDate:Number = 0;
			
			var i:int = 0;
			for(i = 0; i < this.transactions.length; i++){
				tDate = (transactions.getItemAt(i) as Transaction).date.time;
				
				if(rangeStart.time <= tDate && tDate <= rangeEnd.time){
					filteredTransactions.addItem(transactions.getItemAt(i));
				}
			}
			
			for(i = 0; i < this.scheduledTransactions.length; i++){
				tDate = (scheduledTransactions.getItemAt(i) as Transaction).date.time;
				
				if(rangeStart.time <= tDate && tDate <= rangeEnd.time){
					filteredTransactions.addItem(scheduledTransactions.getItemAt(i));
				}
			}
			
			var rangeString:String = Utility.getInstance().formatFriendlyDate(rangeStart) + " to " + Utility.getInstance().formatFriendlyDate(rangeEnd);
			
			return {
				rangeString:rangeString,
				transactions:filteredTransactions
			};
		}
		
		public function modifyTransactionAmount(newAmount:Number, oldAmount:Number):void{
			return;	
		}
		
		public function get nameAndBalance():String{
			var b:Number = this.balance;
			var bStr:String = ( b < 0 ? (-1)*b : b).toFixed(2);
			
			return  "(" + this.accountType + ") " + this.accountName + ": " + (b < 0 ? "-" : "") + "$" + bStr;
		}
		
		public function set nameAndBalance(x:String):void{
			
		}
		
	}
}

